{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "150\n",
      "147\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0    50\n",
       "2    49\n",
       "1    48\n",
       "Name: class, dtype: int64"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 数据集准备\n",
    "# 读取数据集\n",
    "data = pd.read_csv(r\"dataset/iris.arff.csv\", header=0)\n",
    "# data.head(10)  # 查看前面的n行，n默认为5\n",
    "# data.tail(7)  # 查看后面的n行，n默认为5\n",
    "# data.sample(5)  # 随机查看1行，也可在括号内添加数值表示随机查看n行\n",
    "\n",
    "# 添加映射关系，把类别名称映射为数字表示  0  1  2\n",
    "data['class'] = data['class'].map({\"Iris-versicolor\":0,\"Iris-setosa\":1,\"Iris-virginica\":2})\n",
    "# data.sample(5)\n",
    "print(len(data))# 150行\n",
    "# data = data.drop(\"Id\",axis=1)  # 删除列\n",
    "# 去除重复的行\n",
    "if data.duplicated().any():  # 返回True则说明有重复的行\n",
    "    data.drop_duplicates(inplace=True) #删除重复值\n",
    "    print(len(data))# 147行\n",
    "\n",
    "data[\"class\"].value_counts()  # 查看各个类别的鸢尾花记录"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sepallength</th>\n",
       "      <th>sepalwidth</th>\n",
       "      <th>petallength</th>\n",
       "      <th>petalwidth</th>\n",
       "      <th>class</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>49</th>\n",
       "      <td>5.0</td>\n",
       "      <td>3.3</td>\n",
       "      <td>1.4</td>\n",
       "      <td>0.2</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>5.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.6</td>\n",
       "      <td>0.2</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>145</th>\n",
       "      <td>6.7</td>\n",
       "      <td>3.0</td>\n",
       "      <td>5.2</td>\n",
       "      <td>2.3</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29</th>\n",
       "      <td>4.7</td>\n",
       "      <td>3.2</td>\n",
       "      <td>1.6</td>\n",
       "      <td>0.2</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>3.6</td>\n",
       "      <td>1.4</td>\n",
       "      <td>0.2</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     sepallength  sepalwidth  petallength  petalwidth  class\n",
       "49           5.0         3.3          1.4         0.2      1\n",
       "25           5.0         3.0          1.6         0.2      1\n",
       "145          6.7         3.0          5.2         2.3      2\n",
       "29           4.7         3.2          1.6         0.2      1\n",
       "4            5.0         3.6          1.4         0.2      1"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.sample(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {},
   "outputs": [],
   "source": [
    "class KNN:\n",
    "    '''使用Python实现K近邻算法（分类）'''\n",
    "    \n",
    "    def __init__(self,k):\n",
    "        '''初始化方法\n",
    "            k:邻居的个数\n",
    "        '''\n",
    "        self.k = k\n",
    "    \n",
    "    # 训练\n",
    "    # KNN是一种惰性学习（在传进数据的时候才进行计算）\n",
    "    def fit(self,X,y):\n",
    "        '''训练方法\n",
    "            X:类数组类型，形状为：[样本数量(147)，特征数量]，每一个列就是一个特征\n",
    "                待训练的样本特征（属性）\n",
    "                X可以是一个列表，也可以是ndarray类型\n",
    "            y:类数组类型，形状为：[样本数量]   X和y的样本数量一样\n",
    "                每个样本的目标值（标签）\n",
    "        '''\n",
    "        self.X = np.asarray(X)# 转换为 ndarray 数组类型\n",
    "        self.y = np.asarray(y)\n",
    "    \n",
    "    # 预测只需要传入X特征，以此来预测y\n",
    "    def predict(self,X):\n",
    "        '''根据参数传递的样本，对样本数据进行预测\n",
    "           X:类数组类型，形状为：[样本数量(147)，特征数量]，每一个列就是一个特征\n",
    "             待训练的样本特征（属性）\n",
    "             \n",
    "          Returns:\n",
    "          ----\n",
    "          result:数组类型，预测的结果\n",
    "        '''\n",
    "        X = np.asarray(X)\n",
    "        result = []\n",
    "        # 对ndarray数组进行遍历，每次取出数组中的一行\n",
    "        for x in X: \n",
    "            # 要找最近的 k 个点\n",
    "            # x - self.X # 向量对位相减，x是测试集中的一行，X是\n",
    "            dis = np.sqrt(np.sum((x - self.X)**2,axis=1))# 对于测试集中的每一个样本，依次与训练集中的所有样本求距离\n",
    "            index = dis.argsort()  # 能够返回排序后的元素在原来数组（排序前的数组）的位置,目的是根据 x 找到对应的 y\n",
    "            # 进行截断，只取前 k 个元素，取距离最近的 k个元素的索引\n",
    "            index = index[:self.k]\n",
    "            # 返回数组中每个元素出现的次数，元素必须是非负的整数\n",
    "            count = np.bincount(self.y[index]) # 寻找对应标签\n",
    "            # 返回ndarray数组中，值最大的元素对应的索引，该索引就是我们判定的类别\n",
    "            # 最大元素索引，就是出现次数最多的元素\n",
    "            result.append(count.argmax())\n",
    "        return np.asarray(result)\n",
    "    \n",
    "    # 加权重的预测\n",
    "    def predict2(self,X):\n",
    "        '''根据参数传递的样本，对样本数据进行预测\n",
    "           X:类数组类型，形状为：[样本数量(147)，特征数量]，每一个列就是一个特征\n",
    "             待训练的样本特征（属性）\n",
    "             \n",
    "          Returns:\n",
    "          ----\n",
    "          result:数组类型，预测的结果\n",
    "        '''\n",
    "        X = np.asarray(X)\n",
    "        result = []\n",
    "        # 对ndarray数组进行遍历，每次取出数组中的一行\n",
    "        for x in X: \n",
    "            # 要找最近的 k 个点\n",
    "            # x - self.X # 向量对位相减，x是测试集中的一行，X是\n",
    "            dis = np.sqrt(np.sum((x - self.X)**2,axis=1))# 对于测试集中的每一个样本，依次与训练集中的所有样本求距离\n",
    "            index = dis.argsort()  # 能够返回排序后的元素在原来数组（排序前的数组）的位置,目的是根据 x 找到对应的 y\n",
    "            # 进行截断，只取前 k 个元素，取距离最近的 k个元素的索引\n",
    "            index = index[:self.k]\n",
    "            # 返回数组中每个元素出现的次数，元素必须是非负的整数\n",
    "            count = np.bincount(self.y[index],weights=1/dis[index]) # 使用weight考虑权重\n",
    "            # 返回ndarray数组中，值最大的元素对应的索引，该索引就是我们判定的类别\n",
    "            # 最大元素索引，就是出现次数最多的元素\n",
    "            result.append(count.argmax())\n",
    "        return np.asarray(result)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 提取出每个类别的鸢尾花数据\n",
    "t0 = data[data['class']==0]\n",
    "t1 = data[data['class']==1]\n",
    "t2 = data[data['class']==2]\n",
    "# 对每个类别进行洗牌\n",
    "t0 = t0.sample(len(t0),random_state=0)\n",
    "t1 = t1.sample(len(t1),random_state=0)\n",
    "t2 = t2.sample(len(t2),random_state=0)\n",
    "train_X = pd.concat([t0.iloc[:40,:-1],t1.iloc[:40,:-1],t2.iloc[:40,:-1]],axis = 0)# 划分数据集,纵向切割\n",
    "train_y = pd.concat([t0.iloc[:40,-1],t1.iloc[:40,-1],t2.iloc[:40,-1]],axis = 0)\n",
    "test_X = pd.concat([t0.iloc[40:,:-1],t1.iloc[40:,:-1],t2.iloc[40:,:-1]],axis = 0)\n",
    "test_y = pd.concat([t0.iloc[40:,-1],t1.iloc[40:,-1],t2.iloc[40:,-1]],axis = 0)\n",
    "# 创建KNN对象，进行训练和测试\n",
    "knn = KNN(k=10)   \n",
    "# 训练\n",
    "knn.fit(train_X,train_y)\n",
    "# 进行测试，获得测试的结果\n",
    "# result = knn.predict(test_X)   #  k=3 0.962962;    k=4  0.962962;   k=5/6/7/8  0.962962;    k=9/10  1 \n",
    "result = knn.predict2(test_X)   #  k=3 0.962962;    k=4  0.962962;   k=5/6/7/8/9  0.962962;    k=10  1 \n",
    "# display(result)\n",
    "# display(test_y)\n",
    "# display(result == test_y)  # 用True和False来观察正确与否\n",
    "display(np.sum(result==test_y)/len(result))  # 计算正确率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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xlmdHwAAAAAA0PgaKtjp65NGR4tro6Ou7re9e/fqkksu0Y4dO6bd5sCBA4pEItq9e7duvPFGHT16VDfffLO6u7sn/9x1111as2aNHn/8cUnS7t27de211856vwcPHtSSJUu0Z88e5XI53XHHHdN+by6X0+7du7Vq1So988wzZbfJZrP6xCc+oT179uj666/XSy+9pMOHD+u2227TU089pcHBQf3qV7+azSkCAAAAAIRQT48UjUrGuGVPT71HhPmI1nsAhYaHK6vPR3t7u1atWjXjNitWrFB7e7uuuuoqLV26VNdcc43uu+++stseOnRIb731lhYvXqyFCxfOer/xeFz79+9XZ2enent7ZxzPDTfcIElKJBI6ceJE2W0OHjyo66+/XpK0bt06SdLQ0JAeeOABPfTQQ3rjjTd07NixGfcDAAAAAAinnh5p+/ap9ZMnp9a3bavPmDA/DXXHTiJRWX0+Fi1adNptXnjhBV122WV68skn9eabb+rZZ5+ddtsLL7xQW7Zs0Re+8IWK9vvEE0/ozjvv1E9+8hOlUqkZv3emwCjvYx/7mH76059Kku6++2498MAD+uY3v6nVq1frkUcemdVrAAAAAADCKZutrI7G11DBTiYjxWLFtVjM1eshmUzqnnvu0aWXXqrXXntNHR0d0267Zs0abdmyRStXrqxoH8uXL9dtt92mK664QmvXrtVLL700rzGvX79ezz33nLq7u/Xcc8/py1/+sq688kpt2rRJV1xxhSRpZGRkXvsAAAAAAATTyZOV1dH4jLXWtxfr6Oiw+/btK6q98sorOvfcc2f9Gp7neuoMD7s7dTIZ6TQ3sgTa/fffr0ceeUQLFizQggUL9Od//uenNFyul0rfOwAAAABAY4tGy4c4LS3SNM8LQgMwxuy31pa926SheuxILsQJc5BTav369Vq/fn29hwEAAAAAaALpdHGPncI6gqnhgh0AAAAAAFAd+QbJ2ay7c6elxYU6NE4OLoIdAAAAAACayLZtBDlh0lDNkwEAAAAAaDaeJyWTUiTilp5X7xEhSLhjBwAAAACAOvE8NxVqdNStDw1N9btppv6zmLuGu2On9Cldfj61q9SGDRtm/Hp/f7927tx5Sv3555/X888/X6VRAQAAAACaRV/fVKiTNzrq6sBsNFSw0z8woI253GSYY63VxlxO/QMDVdnfli1b5vR9BDsAAAAAAD8MD1dWB0o1zFQsa62OjI1p68iIJGlzW5s25nLaOjKi3nhc1loZY+b02t3d3frkJz+pF198UTt27Ciq5+/IOXbsmFatWqU33nhDf/Inf6L29nZJ0g9/+EP95V/+pd566y098cQT2rp1q7773e9Kkr797W/r6aefnsdRAwAAAACaWSLhpl+VqwOz0TB37BhjtLmtTb3xuLaOjCiya9dkqLO5rW3OoY4k7d27V5dccklRqFPq4MGDWrJkifbs2aNcLqc77rhDkpTL5bR7926tWrVKzzzzjDZt2qTbb79dt99+O6EOAAAAAGBeMhkpFiuuxWKuDsxGwwQ70lS4U2i+oY4ktbe3a9WqVTNuE4/HtX//fnV2dqq3t3eyfsMNN0iSEomETpw4Ma9xAAAAAABQKJWSslmptVUyxi2zWRonY/YaZiqWNNVTp9DGXG7e4c6iRYtOu80TTzyhO++8U9ddd11RfeHChadse9ZZZ+n111+fHPN8gycAAAAAQPNKpQhyMHcNc8dOPtTJT78a7+qanJZV2FC5WpYvX67bbrtNV1xxhdauXauXXnpp2m2vvPJKfec739Fll12mZ599tqrjAgAAAAAAmE7D3LFjjNHiaLSop05+WtbiaHRed8WUe2R5aX3v3r0655xztGDBAh09elS//e1v1d/fP/n1devWTf79ve99r5566qk5jwcAAAAAAMAPxs87YTo6Ouy+ffuKaq+88orOPffcWb9G6dQmpjrVT6XvHQAAAAAA8J8xZr+1tqPc1xpmKlZeaYhDqAMAAAAAAFBewwU7AAAAAAAAmB2CHQAAAAAAgIAi2AEAAAAAAAgogh0AAAAAAICAaqhg58dLfqxf9PxC7xx+p95DAQAAAAAAaHgNFeycGDmh1775mv75I//sW8DT0dGhX//61/rgBz+ow4cP69prr1V3d7e+8pWv6Oqrr5YkvfPOO/riF7+orq4upVIpnThxQv39/err61NnZ6fOP/98vfbaazp27Jg+97nP6aKLLtKXvvQl3X333fMeHwAAAAAA8I/nScmkFIm4pefVe0TV1VDBjiTZE1bjx8d9C3g+8pGPaMeOHbrwwgv15JNPasWKFdq7d68uueQS7dixQ5J0//33q729Xbt27dLSpUv14IMPSpJyuZx2796tVatW6ZlnntHBgwe1ZMkS7dmzR7lcTnfc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\n",
      "text/plain": [
       "<Figure size 1440x720 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 可视化\n",
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 默认情况下，matplotlib不支持中文，需要进行设置\n",
    "mpl.rcParams[\"font.family\"] = \"SimHei\"  # 设置字体为黑体\n",
    "mpl.rcParams[\"axes.unicode_minus\"] = False   # 设置正常显示负号（-）\n",
    "\n",
    "# {\" Iris-versicolor \":0,\" Iris-setosa \":1,\" Iris-virginica \":2}\n",
    "#设置画布的尺寸大小\n",
    "plt.figure(figsize=(20,10))# 单位为 inch\n",
    "# 绘制训练集数据\n",
    "plt.scatter(x=t0[\"sepallength\"][:40], y=t0[\"petallength\"][:40], color='r', label=\"Iris-versicolor\")\n",
    "plt.scatter(x=t1[\"sepallength\"][:40], y=t1[\"petallength\"][:40], color='g', label=\"Iris-setosa\")\n",
    "plt.scatter(x=t2[\"sepallength\"][:40], y=t2[\"petallength\"][:40], color='b', label=\"Iris-virginica\")\n",
    "\n",
    "# 绘制测试集数据\n",
    "right = test_X[ result == test_y]\n",
    "wrong = test_X[ result != test_y]\n",
    "plt.scatter(x=right[\"sepallength\"],y=right[\"petallength\"],color=\"c\",marker=\"x\",label=\"right\")\n",
    "plt.scatter(x=wrong[\"sepallength\"],y=wrong[\"petallength\"],color=\"m\",marker=\">\",label=\"wrong\")\n",
    "plt.xlabel = (\"花萼长度\")\n",
    "plt.ylabel = (\"花瓣长度\")\n",
    "plt.title(\"KNN分类结果显示\")\n",
    "plt.legend(loc=\"best\")\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
